﻿#include <easyx.h>
#include <windows.h>
#include <stdlib.h>
#include <math.h>

// 游戏全局变量
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const int FPS = 60;
const int ballNum = 100;
const int safeRadius = 150;

// 计时器变量
DWORD lastTime = 0;

// 小球结构体
struct Ball {
	int x;
	int y;
	int radius;
	int speedX;
	int speedY;
};

// 飞机结构体
struct Plane {
	int x;
	int y;
	IMAGE img;
	int width;
	int height;
	int collideRadius;
};

// 全局变量
Ball attackBalls[ballNum];
Plane playerPlane;
bool isKeyDown[256] = { false };  // 方向键状态

// 绘制小球
void drawBall(Ball b) {
	setfillcolor(RED);
	fillcircle(b.x, b.y, b.radius);
}

// 绘制飞机
void drawPlane(Plane p) {
	int left = p.x - p.width / 2;
	int top = p.y - p.height / 2;
	putimage(left, top, &p.img);
}

// 初始化飞机
void initPlane() {
	// 加载飞机图片
	if (loadimage(&playerPlane.img, L"./static/pic/plane.png") != 0) {
		playerPlane.width = 40;
		playerPlane.height = 40;
		playerPlane.collideRadius = 20;
	}
	else {
		playerPlane.width = playerPlane.img.getwidth();
		playerPlane.height = playerPlane.img.getheight();
		playerPlane.collideRadius = (int)(sqrt(playerPlane.width * playerPlane.width + playerPlane.height * playerPlane.height) / 3);
	}
	// 初始位置：窗口中心（鼠标未移动时的默认位置）
	playerPlane.x = WINDOW_WIDTH / 2;
	playerPlane.y = WINDOW_HEIGHT / 2;

	//隐藏系统默认光标（让飞机替代光标）
	ShowCursor(FALSE);
}

// 初始化小球
void initBalls() {
	srand(GetTickCount());
	for (int i = 0; i < ballNum; i++) {
		attackBalls[i].radius = 3;
		int x, y;
		double distance = 0;
		//安全区逻辑
		do {
			x = rand() % (WINDOW_WIDTH - 2 * attackBalls[i].radius) + attackBalls[i].radius;
			y = rand() % (WINDOW_HEIGHT - 2 * attackBalls[i].radius) + attackBalls[i].radius;
			double dx = x - playerPlane.x;
			double dy = y - playerPlane.y;
			distance = sqrt(dx * dx + dy * dy);
		} while (distance < safeRadius + attackBalls[i].radius + playerPlane.collideRadius);

		//小球速度（减慢后）
		int speedX = rand() % 6 - 3;
		if (speedX == 0) speedX = 1;
		int speedY = rand() % 6 - 3;
		if (speedY == 0) speedY = 1;

		attackBalls[i].x = x;
		attackBalls[i].y = y;
		attackBalls[i].speedX = speedX;
		attackBalls[i].speedY = speedY;
	}
}

//更新小球位置
void updateBalls() {
	for (int i = 0; i < ballNum; i++) {
		attackBalls[i].x += attackBalls[i].speedX;
		attackBalls[i].y += attackBalls[i].speedY;

		//边界修正
		if (attackBalls[i].x - attackBalls[i].radius <= 0) {
			attackBalls[i].x = attackBalls[i].radius;
			attackBalls[i].speedX = -attackBalls[i].speedX;
		}
		if (attackBalls[i].x + attackBalls[i].radius >= WINDOW_WIDTH) {
			attackBalls[i].x = WINDOW_WIDTH - attackBalls[i].radius;
			attackBalls[i].speedX = -attackBalls[i].speedX;
		}
		if (attackBalls[i].y - attackBalls[i].radius <= 0) {
			attackBalls[i].y = attackBalls[i].radius;
			attackBalls[i].speedY = -attackBalls[i].speedY;
		}
		if (attackBalls[i].y + attackBalls[i].radius >= WINDOW_HEIGHT) {
			attackBalls[i].y = WINDOW_HEIGHT - attackBalls[i].radius;
			attackBalls[i].speedY = -attackBalls[i].speedY;
		}
	}
}

//碰撞检测
int isCollided() {
	for (int i = 0; i < ballNum; i++) {
		double dx = playerPlane.x - attackBalls[i].x;
		double dy = playerPlane.y - attackBalls[i].y;
		double distance = sqrt(dx * dx + dy * dy);
		if (distance <= playerPlane.collideRadius + attackBalls[i].radius) {
			return 1;
		}
	}
	return 0;
}

//绘制计时区域
void drawTimerArea(double insistTime) {
	settextcolor(WHITE);
	settextstyle(30, 0, L"微软雅黑");

	TCHAR buffer[50];
	swprintf(buffer, 50, L"已坚持： %.2f 秒", insistTime);

	int textWidth = textwidth(buffer);
	int textHeight = textheight(buffer);

	int rectPadding = 40;
	int rectWidth = textWidth + rectPadding;
	int rectHeight = 50;

	int rectX = (WINDOW_WIDTH - rectWidth) / 2;
	int rectY = 0;

	setfillcolor(BLACK);
	fillrectangle(rectX, rectY, rectX + rectWidth, rectY + rectHeight);

	int textX = rectX + (rectWidth - textWidth) / 2;
	int textY = rectY + (rectHeight - textHeight) / 2;

	outtextxy(textX, textY, buffer);
}

// 初始化游戏
void initGameWindow() {
	initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);
	SetWindowText(GetHWnd(), L"坚持20秒");
	setbkcolor(BLACK);
	cleardevice();
	lastTime = GetTickCount();
	initPlane();    // 初始化飞机
	initBalls();
}

// 显示3秒倒计时
void showCountdown() {
	BeginBatchDraw();
	for (int i = 3; i >= 1; i--) {
		cleardevice();  // 清屏
		settextcolor(WHITE);
		settextstyle(100, 0, L"微软雅黑");  // 大字体显示倒计时

		TCHAR num[2];
		swprintf(num, 2, L"%d", i);
		int textWidth = textwidth(num);
		int textHeight = textheight(num);

		// 文字居中显示
		outtextxy(
			WINDOW_WIDTH / 2 - textWidth / 2,
			WINDOW_HEIGHT / 2 - textHeight / 2,
			num
		);
		FlushBatchDraw();
		Sleep(1000);  // 停留1秒
	}
	cleardevice();
	FlushBatchDraw();
	EndBatchDraw();
}

int main() {
	// 弹出开始提示框
	if (MessageBox(
		GetHWnd(),
		L"准备开始游戏！你需要控制飞机躲避红色小球，坚持20秒即可获胜。\n点击【确定】开始游戏，【取消】退出。",
		L"游戏说明",
		MB_OKCANCEL | MB_ICONINFORMATION
	) != IDOK) {
		return 0;  // 用户取消，直接退出
	}
	initGameWindow();

	// 显示3秒倒计时
	showCountdown();

	// 倒计时结束后，重置游戏开始时间
	lastTime = GetTickCount();

	BeginBatchDraw();

	while (true) {
		//鼠标移动直接赋值给飞机
		ExMessage msg;
		while (peekmessage(&msg, EX_MOUSE | EX_KEY)) {
			// 鼠标移动：飞机位置 = 鼠标位置（实时同步）
			if (msg.message == WM_MOUSEMOVE) {
				playerPlane.x = msg.x;
				playerPlane.y = msg.y;
			}
			// 方向键控制
			else if (msg.message == WM_KEYDOWN) {
				isKeyDown[msg.vkcode] = true;
			}
			else if (msg.message == WM_KEYUP) {
				isKeyDown[msg.vkcode] = false;
			}
		}

		//方向键控制
		const int MOVE_SPEED = 5;
		if (isKeyDown[VK_LEFT])  playerPlane.x -= MOVE_SPEED;
		if (isKeyDown[VK_RIGHT]) playerPlane.x += MOVE_SPEED;
		if (isKeyDown[VK_UP])    playerPlane.y -= MOVE_SPEED;
		if (isKeyDown[VK_DOWN])  playerPlane.y += MOVE_SPEED;

		// 边界限制（防止飞机超出窗口）
		if (playerPlane.x < playerPlane.width / 2)
			playerPlane.x = playerPlane.width / 2;
		if (playerPlane.x > WINDOW_WIDTH - playerPlane.width / 2)
			playerPlane.x = WINDOW_WIDTH - playerPlane.width / 2;
		if (playerPlane.y < playerPlane.height / 2)
			playerPlane.y = playerPlane.height / 2;
		if (playerPlane.y > WINDOW_HEIGHT - playerPlane.height / 2)
			playerPlane.y = WINDOW_HEIGHT - playerPlane.height / 2;

		// 清屏
		cleardevice();

		// 计算时间
		DWORD currentTime = GetTickCount();
		double insistTime = (currentTime - lastTime) / 1000.0;

		// 更新小球
		updateBalls();

		// 碰撞检测
		if (isCollided()) {
			settextcolor(RED);
			settextstyle(50, 0, L"微软雅黑");
			TCHAR endMsg[100];
			swprintf(endMsg, 100, L"游戏结束！共坚持：%.2f秒", insistTime);
			outtextxy(WINDOW_WIDTH / 2 - 250, WINDOW_HEIGHT / 2 - 25, endMsg);
			break;
		}

		// 胜利条件
		if (insistTime >= 20.0) {
			settextcolor(GREEN);
			settextstyle(50, 0, L"微软雅黑");
			outtextxy(WINDOW_WIDTH / 2 - 200, WINDOW_HEIGHT / 2 - 25, L"恭喜你坚持到了20秒！");
			break;
		}

		// 绘制顺序：小球→飞机→计时区
		for (int i = 0; i < ballNum; i++) {
			drawBall(attackBalls[i]);
		}
		drawPlane(playerPlane);  // 飞机即光标，最后绘制确保在顶层
		drawTimerArea(insistTime);

		FlushBatchDraw();
		Sleep(1000 / FPS);
	}

	// 游戏结束后显示光标
	ShowCursor(TRUE);
	FlushBatchDraw();
	Sleep(3000);
	closegraph();
	return 0;
}